#include "stdafx.h"
#include "apSocketIO.h"

#pragma comment(lib, "sioclient")
#pragma comment(lib, "libboost_regex-vc140-mt-gd-1_59")
#pragma comment(lib, "libboost_chrono-vc140-mt-gd-1_59")
#pragma comment(lib, "libboost_date_time-vc140-mt-gd-1_59")
#pragma comment(lib, "libboost_system-vc140-mt-gd-1_59")
//#pragma comment(lib, "libeay32")
//#pragma comment(lib, "ssleay32")

apSocketIO::apSocketIO()
	:m_participants(-1), m_connected(false)
{
}


apSocketIO::~apSocketIO()
{
}

void apSocketIO::on_connected()
{
	std::cout << "sio connedted" << std::endl;

	_lock.lock();
	_cond.notify_all();
	m_connected = true;
	_lock.unlock();
}

void apSocketIO::on_close(client::close_reason const& reason)
{
	std::cout << "sio closed: " << reason << std::endl;
	m_connected = false;
}

void apSocketIO::on_fail()
{
	std::cout << "sio failed " << std::endl;
	m_connected = false;
}

void apSocketIO::on_ack()
{

}

void apSocketIO::connect(const char* url)
{
	m_client.set_open_listener(std::bind(&apSocketIO::on_connected, this));
	m_client.set_close_listener(std::bind(&apSocketIO::on_close, this, std::placeholders::_1));
	m_client.set_fail_listener(std::bind(&apSocketIO::on_fail, this));

	std::string uri = url;
	m_client.connect(uri);

	_lock.lock();
	if (!m_connected)
	{
		_cond.wait(_lock);
	}
	_lock.unlock();

	m_current_socket = m_client.socket();
}

void apSocketIO::login(const char* username)
{
	if (!m_current_socket)
		return;

	string nickname = username;
	m_current_socket->on("login", sio::socket::event_listener_aux(
		[&](string const& name, message::ptr const& data, bool isAck, message::list &ack_resp) {
		_lock.lock();
		m_participants = data->get_map()["numUsers"]->get_int();
		bool plural = m_participants != 1;
		HIGHLIGHT("Welcome to Socket.IO Chat-\nthere" << (plural ? " are " : "'s ") <<
			m_participants << (plural ? " participants" : " participant"));
		_cond.notify_all();
		_lock.unlock();
		m_current_socket->off("login");
	}));
	m_current_socket->emit("add user", nickname);
	_lock.lock();
	if (m_participants < 0) {
		_cond.wait(_lock);
	}
	_lock.unlock();

	bind_events();
}

void apSocketIO::bind_events()
{
	m_current_socket->on("new message", 
		sio::socket::event_listener_aux(
			[&](string const& name, message::ptr const& data, bool isAck, message::list &ack_resp)
	{
		_lock.lock();
		string user = data->get_map()["username"]->get_string();
		string message = data->get_map()["message"]->get_string();
		EM(user << ":" << message);
		_lock.unlock();
	}));

	m_current_socket->on("user joined",
		sio::socket::event_listener_aux(
			[&](string const& name, message::ptr const& data, bool isAck, message::list &ack_resp)
	{
		_lock.lock();
		string user = data->get_map()["username"]->get_string();
		m_participants = data->get_map()["numUsers"]->get_int();
		bool plural = m_participants != 1;

		//     abc "
		HIGHLIGHT(user << " joined" << "\nthere" << (plural ? " are " : "'s ") <<
			m_participants << (plural ? " participants" : " participant"));
		_lock.unlock();
	}));

	m_current_socket->on("user left",
		sio::socket::event_listener_aux(
			[&](string const& name, message::ptr const& data, bool isAck, message::list &ack_resp)
	{
		_lock.lock();
		string user = data->get_map()["username"]->get_string();
		m_participants = data->get_map()["numUsers"]->get_int();
		bool plural = m_participants != 1;
		HIGHLIGHT(user << " left" << "\nthere" << (plural ? " are " : "'s ") << 
			m_participants << (plural ? " participants" : " participant"));
		_lock.unlock();
	}));
}

void apSocketIO::send_message(const char* to, const char* msg)
{
	std::string messsage = msg;
	m_current_socket->emit("new message", messsage);
}

void apSocketIO::addObserver(SocketObserver *obs)
{

}

void apSocketIO::removeObserver(SocketObserver *obs)
{

}

void apSocketIO::logout()
{

}

void apSocketIO::disconnect()
{

}